#pragma once

#include <sys/epoll.h>
#include "Err.hpp"
#include "Log.hpp"

static const int DEFAULT_EPFD = -1;

class Epoller
{
public:
    Epoller()
        : _epfd(DEFAULT_EPFD)
    {
    }


    /// @brief 创建一个epoll句柄
    void Create()
    {
        _epfd = epoll_create(1);
        if (_epfd < 0)
        {
            logMessage(Fatal, "epoll_create error, code: %d, errstring: %s", errno, strerror(errno));
            exit(EPOLL_CREAT_ERR);
        }
    }

    /// @brief 注册新的fd到epfd中
    /// @return 注册是否成功
    bool AddEvent(int fd, int events)
    {
        struct epoll_event event;
        event.events = events;
        event.data.fd = fd;
        int ret = epoll_ctl(_epfd, EPOLL_CTL_ADD, fd, &event);
        if (ret < 0)
        {
            logMessage(Fatal, "epoll_ctl error, code: %d, errstring: %s", errno, strerror(errno));
            return false;
        }
        return true;
    }

    /// @brief 从epfd中删除fd
    /// @return 删除是否成功
    bool DelEvent(int fd)
    {
        int ret = epoll_ctl(_epfd, EPOLL_CTL_DEL, fd, nullptr);
        if (ret == -1)
        {
            logMessage(Fatal, "epoll_ctl error, code: %d, errstring: %s", errno, strerror(errno));
            return false;
        }
        return true;
    }

    /// @brief 获取epoll监控的已经就绪的事件
    int Wait(struct epoll_event *revs, int num, int timeout)
    {
        return epoll_wait(_epfd, revs, num, timeout);
    }

    /// @brief 关闭epoll句柄
    void Close()
    {
        if(_epfd != DEFAULT_EPFD)
            close(_epfd);
    }

private:
    int _epfd;
};